"""
真倾角计算工具主程序
版本：1.2
功能特性：
1. CSV数据导入与解析
2. 表格数据实时计算
3. 批量数据修改功能
4. 动态行管理功能
"""

import sys
import csv
from PySide2.QtWidgets import (QApplication, QMainWindow, QWidget, QTableWidget,
                               QTableWidgetItem, QPushButton, QVBoxLayout, QHeaderView,
                               QHBoxLayout, QLabel, QLineEdit)
from PySide2.QtCore import Qt
from business.business3 import TrueInclinationCalculator  # 计算核心模块

class MainWindow(QMainWindow):
    def __init__(self):
        """主窗口构造函数"""
        super().__init__()

        # ==================== 界面初始化 ====================
        # region 窗口基础设置
        self.setWindowTitle("真倾角计算工具 v1.2")  # 设置窗口标题
        self.setGeometry(100, 100, 800, 600)       # 初始位置(x,y)和尺寸(w,h)
        # endregion

        # region 中央部件布局
        central_widget = QWidget()
        self.setCentralWidget(central_widget)      # 设置中心部件
        main_layout = QVBoxLayout(central_widget)  # 垂直布局
        main_layout.setContentsMargins(10, 10, 10, 10)  # 设置边距(左,上,右,下)
        main_layout.setSpacing(15)  # 控件间距
        # endregion

        # ==================== 功能控件区 ====================
        # region 操作按钮组
        btn_layout = QHBoxLayout()
        # 导入CSV按钮
        self.import_btn = QPushButton("导入CSV数据", self)
        self.import_btn.setToolTip("支持格式：UTF-8编码的CSV文件")  # 鼠标悬停提示
        self.import_btn.clicked.connect(self.import_csv)  # 绑定点击事件
        btn_layout.addWidget(self.import_btn)

        # 添加行按钮
        self.add_row_btn = QPushButton("添加新行", self)
        self.add_row_btn.setToolTip("在表格末尾添加新数据行")
        self.add_row_btn.clicked.connect(self.add_new_row)
        btn_layout.addWidget(self.add_row_btn)

        main_layout.addLayout(btn_layout)  # 将按钮组加入主布局
        # endregion

        # region 批量修改组件
        h_layout = QHBoxLayout()
        # 批量修改标签
        self.batch_edit_label = QLabel("批量修改第四列数据:")
        # 输入框
        self.batch_edit_input = QLineEdit()
        self.batch_edit_input.setPlaceholderText("输入井轨边方位值")  # 占位提示文本
        # 应用按钮
        self.apply_batch_btn = QPushButton("应用")
        self.apply_batch_btn.clicked.connect(self.apply_batch_update)

        h_layout.addWidget(self.batch_edit_label)
        h_layout.addWidget(self.batch_edit_input)
        h_layout.addWidget(self.apply_batch_btn)
        main_layout.addLayout(h_layout)
        # endregion

        # ==================== 数据表格区 ====================
        self.table = QTableWidget()
        main_layout.addWidget(self.table)
        self._initialize_table()  # 初始化表格结构
        self.table.cellChanged.connect(self._handle_cell_change)  # 单元格变更事件绑定

    def _initialize_table(self):
        """初始化表格结构和表头"""
        # 表格维度设置
        self.table.setColumnCount(5)  # 5列：4输入+1结果
        self.table.setRowCount(3)     # 3行：标题行+单位行+1数据行

        # region 表头设置
        # 合并单元格（起始行，起始列，合并行数，合并列数）
        self.table.setSpan(0, 0, 1, 4)  # 合并前四列为"输入参数"

        # 设置表头单元格
        self._set_header_cell(0, 0, "输入参数", "地层参数输入区域")
        self._set_header_cell(0, 4, "计算结果", "视倾角计算结果")

        # 列标题
        column_titles = ["深度", "地层真倾向", "地层真倾角", "井轨边方位", "沿井轨迹视倾角"]
        for col, title in enumerate(column_titles):
            self._set_header_cell(1, col, title, "数据列标题")

        # 单位说明
        units = ["m", "deg", "deg", "deg", "deg"]
        for col, unit in enumerate(units):
            self._set_header_cell(2, col, unit, "测量单位")

        # 锁定表头编辑
        for row in range(3):
            for col in range(5):
                if item := self.table.item(row, col):
                    item.setFlags(item.flags() & ~Qt.ItemIsEditable)  # 移除可编辑标志
        # endregion

        # 表格显示设置
        self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)  # 自动拉伸列宽
        self.table.verticalHeader().setDefaultSectionSize(30)  # 行高

    def _set_header_cell(self, row, col, text, tooltip=""):
        """辅助方法：设置表头单元格
        Args:
            row: 行索引
            col: 列索引
            text: 显示文本
            tooltip: 悬停提示信息
        """
        item = QTableWidgetItem(text)
        item.setTextAlignment(Qt.AlignCenter)  # 居中对齐
        item.setToolTip(tooltip)               # 提示信息
        self.table.setItem(row, col, item)

    def _handle_cell_change(self, row, column):
        """处理单元格内容变更事件
        触发条件：数据行（row>=3）的前四列（0-3列）内容变化
        """
        if column > 3 or row < 3:  # 仅处理数据行的前四列
            return

        # 临时断开信号防止递归触发
        self.table.cellChanged.disconnect(self._handle_cell_change)
        try:
            self._update_calculation_results([row])  # 更新当前行计算结果
        finally:
            self.table.cellChanged.connect(self._handle_cell_change)  # 重新连接

    def _update_calculation_results(self, rows):
        """批量更新计算结果
        Args:
            rows: 需要更新的行号列表（基于0的索引）
        """
        for r in rows:
            try:
                # 获取输入参数（深度、真倾向、真倾角、井轨方位）
                input_params = [
                    self._get_numeric_cell_value(r, 0),
                    self._get_numeric_cell_value(r, 1),
                    self._get_numeric_cell_value(r, 2),
                    self._get_numeric_cell_value(r, 3)
                ]
                # 调用计算模块（保留9位小数）
                result = TrueInclinationCalculator.calculate_view_inclination(*input_params)
                result_text = f"{result:.9f}"
            except (ValueError, TypeError):  # 数值转换失败
                result_text = "无效输入"
            except AttributeError:  # 单元格不存在
                result_text = "数据缺失"

            # 设置结果单元格
            result_item = QTableWidgetItem(result_text)
            result_item.setTextAlignment(Qt.AlignCenter)
            result_item.setFlags(result_item.flags() & ~Qt.ItemIsEditable)  # 禁止编辑
            self.table.setItem(r, 4, result_item)

    def _get_numeric_cell_value(self, row, column):
        """获取单元格数值
        Returns:
            float: 单元格数值
        Raises:
            AttributeError: 单元格不存在
            ValueError: 非数值内容
        """
        if cell := self.table.item(row, column):
            return float(cell.text())
        raise AttributeError(f"单元格({row},{column})不存在")

    def apply_batch_update(self):
        """批量更新第四列数据"""
        new_value = self.batch_edit_input.text()

        # 输入验证
        try:
            float(new_value)  # 确保输入为有效数字
        except ValueError:
            return  # 无效输入静默失败

        # 批量更新流程
        self.table.cellChanged.disconnect(self._handle_cell_change)  # 暂停事件监听
        try:
            for row in range(3, self.table.rowCount()):  # 从第4行开始（索引3）
                item = self.table.item(row, 3) or QTableWidgetItem()  # 获取或新建单元格
                item.setTextAlignment(Qt.AlignCenter)
                item.setText(new_value)
                self.table.setItem(row, 3, item)
        finally:
            self.table.cellChanged.connect(self._handle_cell_change)  # 恢复监听

        # 触发结果更新
        self._update_calculation_results(range(3, self.table.rowCount()))

    def add_new_row(self):
        """添加新数据行"""
        current_row_count = self.table.rowCount()
        self.table.setRowCount(current_row_count + 1)  # 扩展行数

        # 初始化输入列（0-3列）
        for col in range(4):
            item = QTableWidgetItem("0.0")  # 默认值
            item.setTextAlignment(Qt.AlignCenter)
            self.table.setItem(current_row_count, col, item)

        # 初始化结果列（4列）
        result_item = QTableWidgetItem("")
        result_item.setTextAlignment(Qt.AlignCenter)
        result_item.setFlags(result_item.flags() & ~Qt.ItemIsEditable)
        self.table.setItem(current_row_count, 4, result_item)

        # 自动计算新行
        self._update_calculation_results([current_row_count])

    def import_csv(self):
        """处理CSV文件导入"""
        from PySide2.QtWidgets import QFileDialog

        # 文件选择对话框
        csv_file, _ = QFileDialog.getOpenFileName(
            parent=self,
            caption="选择测量数据文件",
            filter="CSV文件 (*.csv);;所有文件 (*)",
            options=QFileDialog.DontUseNativeDialog  # 强制使用Qt对话框
        )
        if not csv_file:
            return  # 用户取消选择

        try:
            # 读取并过滤空行
            with open(csv_file, 'r', encoding='utf-8-sig') as f:  # 处理BOM头
                raw_data = csv.reader(f)
                valid_rows = [row for row in raw_data if any(field.strip() for field in row)]

            if not valid_rows:
                raise ValueError("CSV文件内容为空")
        except Exception as e:
            print(f"[错误] 文件读取失败：{str(e)}")
            return

        # 清空现有数据（保留3行表头）
        self.table.setRowCount(3 + len(valid_rows))

        # 填充数据
        for row_idx, csv_row in enumerate(valid_rows):
            table_row = 3 + row_idx  # 数据从第4行开始

            # 填充前四列
            for col in range(4):
                value = csv_row[col].strip() if col < len(csv_row) else ""
                cell = QTableWidgetItem(value)
                cell.setTextAlignment(Qt.AlignCenter)
                self.table.setItem(table_row, col, cell)

            # 计算结果列
            try:
                params = [float(csv_row[i]) for i in range(4)]  # 前四列转为float
                result = TrueInclinationCalculator.calculate_view_inclination(*params)
                result_text = f"{result:.6f}"  # 结果保留6位小数
            except (IndexError, ValueError, TypeError):  # 数据不完整或格式错误
                result_text = ""

            # 设置结果单元格
            result_cell = QTableWidgetItem(result_text)
            result_cell.setTextAlignment(Qt.AlignCenter)
            result_cell.setFlags(result_cell.flags() & ~Qt.ItemIsEditable)
            self.table.setItem(table_row, 4, result_cell)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    app.setStyle("Fusion")  # 设置现代UI风格
    main_window = MainWindow()
    main_window.show()
    sys.exit(app.exec_())
